package com.cqw.auth.config.filter;

import cn.hutool.json.JSONUtil;
import com.cqw.auth.config.RedisClient;
import com.cqw.auth.domain.MyUser;
import com.cqw.auth.enums.CodeEnum;
import com.cqw.auth.utils.JwtTokenUtil;
import com.cqw.auth.utils.ResultJSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

/**
 * 验证用户名密码正确后 生成一个token并将token返回给客户端
 */
@Slf4j
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    private WebApplicationContext wac;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager)
    {
        this.authenticationManager = authenticationManager;
    }

    /**
     * 验证操作 接收并解析用户凭证
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        wac = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        // 从输入流中获取到登录的信息
        // 创建一个token并调用authenticationManager.authenticate() 让Spring security进行验证
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getParameter("username"),request.getParameter("password")));
    }

    /**
     * 验证【成功】后调用的方法
     * 若验证成功 生成token并返回
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException {
        MyUser user = (MyUser) authResult.getPrincipal();

        // 从User中获取权限信息
        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        // 创建Token
        String token = JwtTokenUtil.createToken(user.getUsername(), authorities.toString());


        RedisClient redisClient = wac.getBean(RedisClient.class);
        redisClient.setEx(JwtTokenUtil.REDIS_TOKEN + user.getUsername() + authorities.toString() ,token,JwtTokenUtil.EXPIRITION, TimeUnit.MILLISECONDS );
        log.info("key:{}" , JwtTokenUtil.REDIS_TOKEN + user.getUsername()+ authorities.toString());
        String ss = redisClient.get(JwtTokenUtil.REDIS_TOKEN + user.getUsername() + authorities.toString());

        log.info("token:{}" , ss);
        // 设置编码 防止乱码问题
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        // 在请求头里返回创建成功的token
        // 设置请求头为带有"Bearer "前缀的token字符串
        response.setHeader("token", JwtTokenUtil.TOKEN_PREFIX + token);

        // 处理编码方式 防止中文乱码
        response.setContentType("text/json;charset=utf-8");
        // 将反馈塞到HttpServletResponse中返回给前台
        response.getWriter().write(JSONUtil.toJsonStr(new ResultJSON(CodeEnum.USER_LOGIN_SUCCESS)));
    }

    /**
     * 验证【失败】调用的方法
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        // 处理编码方式 防止中文乱码
        response.setContentType("text/json;charset=utf-8");
        // 将反馈塞到HttpServletResponse中返回给前台
        response.getWriter().write(JSONUtil.toJsonStr(new ResultJSON(CodeEnum.USER_NOT_EXIST_FAILURE)));
    }
}
